﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Globalization;
using System.IO;
using Microsoft.Office.Project.EPMAuditing.Library;

namespace Microsoft.Office.Project.EPMAuditing.AuditListenerCatalog
{
    public abstract class BaseFileAuditListener : AuditListener
    {
        private const int MAX_FILE_SIZE = 1024000;
        private const string DEFAULT_BASE_FILE_NAME = "EPM Auditing Log - ";

        private TextWriter _auditFileStream;
        private string _openFileName = string.Empty;

        private string _fileBaseName;
        private string _fileDirectory;
        private bool _fileOpen;

        #region Construction/Destruction

        protected BaseFileAuditListener() : this(DefaultFileDirectory, String.Empty) { }

        protected BaseFileAuditListener(string fileDirectory) : this(fileDirectory, String.Empty) { }

        protected BaseFileAuditListener(string fileDirectory, string fileBaseName)
        {
            _fileOpen = false;

            if (!String.IsNullOrEmpty(fileDirectory))
                _fileDirectory = fileDirectory;
            else
                _fileDirectory = string.Empty;

            if (!String.IsNullOrEmpty(fileBaseName))
                _fileBaseName = fileBaseName;
            else
                _fileBaseName = DEFAULT_BASE_FILE_NAME;
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                // Release managed resources.
                CloseAuditFile();
            }
            // Release unmanaged resources.
            // Set large fields to null.

            // Call Dispose on your base class.
            base.Dispose(disposing);
        }

        public void StartNewFile()
        {
            CloseAuditFile();
            OpenNewAuditFile();
        }

        #endregion

        #region Utility Methods

        private static string DefaultFileDirectory
        {
            get
            {
                string fullPath = Assembly.GetExecutingAssembly().Location;
                string directory = fullPath.Substring(0, fullPath.LastIndexOf(@"\", StringComparison.OrdinalIgnoreCase) + 1);
                return String.Format(CultureInfo.InvariantCulture, @"{0}Audit Logs\", directory);
            }
        }
        
        private void OpenNewAuditFile()
        {
            if (_fileOpen)
                CloseAuditFile();

            _openFileName = NewFileName();
            _auditFileStream = new StreamWriter(_openFileName);
            _fileOpen = true;
            AddHeader();

        }

        private void CloseAuditFile()
        {
            AddFooter();
            _auditFileStream.Flush();
            _auditFileStream.Close();
            _fileOpen = false;
        }

        private void StartNewFileIfPastSize(long fileSize)
        {
            FileInfo fi = new FileInfo(_openFileName);
            if (fi.Length > fileSize)
            {
                StartNewFile();
            }
        }


        #endregion

        #region Protected Properties

        protected string FileBaseName
        {
            get { return _fileBaseName; }
            set { _fileBaseName = value; }
        }

        protected string FileDirectory
        {
            get { return _fileDirectory; }
            set { _fileDirectory = value; }
        }

        protected bool FileOpen
        {
            get { return _fileOpen; }
            set { _fileOpen = value; }
        }

        #endregion

        #region Protected Methods

        protected abstract string NewFileName();

        protected abstract void AddHeader();

        protected abstract void AddFooter();

        protected void WriteToFile(string message)
        {
            if (!_fileOpen)
            {
                OpenNewAuditFile();
            }

            // Write the data to the file
            _auditFileStream.WriteLine(message);

            StartNewFileIfPastSize(MAX_FILE_SIZE);

        }

        #endregion

    }
}
